I wrote a test that uses Mockito 1.9.5. I have an HttpGet and an HttpPost which an HttpClient execute, and I'm testing to verify that the response from each returns the expected result in the form of an input stream.
The issue is that while using
Mockito.when(mockedClient.execute(any(HttpPost.class))).thenReturn(postResponse) and Mockito.when(mockedClient.execute(any(HttpGet.class))).thenReturn(getResponse), where the responses are different objects, mockedClient.execute() always returns getResponse.
The test I've written is below:
private InputStream postContent;
private InputStream getContent;
#Mock
private FilesHandler hand;
#Mock
private MockHttpClient client;
private MockHttpEntity postEntity;
private MockHttpEntity getEntity;
private MockHttpResponse postResponse;
private MockHttpResponse getResponse;
private String imgQuery = "someQuery";
private ParametersHandler ph;
private FileHandlerImpl fileHand;
private String indexFolder = "src/test/resources/misc/";
private String indexFile = "index.csv";
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
try {
postContent = new FileInputStream(indexFolder + "testContent.txt");
postEntity = new MockHttpEntity(postContent);
postResponse = new MockHttpResponse(postEntity, new BasicStatusLine(new ProtocolVersion("http", 1, 1), 200, "postReasonPhrase"));
getContent = new FileInputStream(indexFolder + "testContent.txt");
getEntity = new MockHttpEntity(getContent);
getResponse = new MockHttpResponse(getEntity, new BasicStatusLine(new ProtocolVersion("http", 1, 1), 200, "getReasonPhrase"));
ph = new ParametersHandler();
fileHand = new FileHandlerImpl(client, ph, indexFolder, indexFile);
} catch (Exception e) {
failTest(e);
}
}
#Test
public void getFileWhenEverythingJustWorks() {
try {
Mockito.when(client.execute(Mockito.any(HttpPost.class))).thenReturn(postResponse);
Mockito.when(client.execute(Mockito.any(HttpGet.class))).thenReturn(getResponse);
fileHand.getFile(hand, imgQuery, ph, "I");
Mockito.verify(hand).rebuildIndex(Mockito.any(String.class), Mockito.any(Map.class), Mockito.any(Map.class), hand);
} catch (IOException e) {
failTest(e);
}
}
A shortened version of the method being tested is below.
public void getFile(FilesHandler fileHandlerFl, String query, ParametersHandler ph, String type) {
JsonFactory factory = new JsonFactory();
HttpPost post = preparePost(query, factory);
CloseableHttpResponse response = client.execute(post);
String uri = "https://someuri.com" + "/File";
HttpGet get = new HttpGet(uri);
setParameters(get);
response.close();
response = client.execute(get);
}
As always, any help you can provide is appreciated.
Despite what it would mean when read in English, in Mockito 1.x, any(HttpGet.class) matches any value and not just any HttpGet. The parameter is only used to save a cast previous to Java 8.
From the Matchers.any(Class) documentation:
Matches any object, including nulls
This method doesn't do type checks with the given parameter, it is only there to avoid casting in your code. This might however change (type checks could be added) in a future major release.
Use isA(HttpGet.class) and isA(HttpPost.class) instead, and see Brice's comment below about future changes to the any(Class<?> clazz) matcher.
Related
I am currently receiving the following error for the http request am sending. I am trying to send a JSON Array list to trigger a method in the receiving end so as it saves the list in its database.
The 500 Internal Server Error is a very general HTTP status code that means something has gone wrong on the website's server, but the server could not be more specific on what the exact problem is.
Websites phrase 500 errors in many ways but they're all basically saying the same thing: there's a general server issue going on right now.
Most of the time there isn't anything you can do but contact the website directly and then wait on them to fix it.
In the off chance there is a problem on your end, try clearing the cache and deleting any cookies from the site with the error.
Please find the error below:
org.springframework.web.client.HttpServerErrorException: 500 Internal Server
public static String FRONT_URL;
public static String BACK_URL;
public static final String REST_SYNC = "rest/sync";
public static final String REST_API = "rest/api";
private Logger log = Logger.getLogger(FrontSynchronizer.class);
static final Logger synclog = Logger.getLogger("sync");
ResourceBundle rb = ResourceBundle.getBundle("bundles.sync-application-resources", Locale.getDefault());
//method sending the request
public void syncApplications(List<SchemeApplication> accList) {
schemeApplicationDto=new SchemeApplicationDto();
FRONT_URL = rb.getString("sync.front.url").concat(REST_SYNC);
BACK_URL = rb.getString("sync.back.url").concat(REST_API);
JSONArray array = new JSONArray();
if (accList != null && accList.size() > 0) {
for (SchemeApplication student : accList) {
schemeApplicationDto.setId(student.getId());
schemeApplicationDto.setAccountID(student.getAccountID());
schemeApplicationDto.setNoOfPersonsEmployedLocal(student.getNoOfPersonsEmployedLocal());
schemeApplicationDto.setLocalmainclients(student.getLocalmainclients());
JSONObject studentJSON = new JSONObject(schemeApplicationDto);
array.put(studentJSON);
}
}
HttpHeaders headers = new HttpHeaders();
JSONObject object = new JSONObject();
object.put("array", array);
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = this.createnewTemplate();
String url = BACK_URL.concat("/application");
HttpEntity<String> requestEntity = new HttpEntity<String>(object.toString(), headers);
ResponseEntity<Boolean> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity,
Boolean.class);
if (responseEntity.getBody())
{
for(SchemeApplication scheme:accList) {
schemeApplicationService.getDao().delete(scheme);
}
}
}
public RestTemplate createnewTemplate() {
// RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectTimeout(120000);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
return restTemplate;
}
// method that needs to process the request
//The method is trying to send an Array list so as the receiving end can receive the list and save it in its database.
#RequestMapping(value = "application", method = RequestMethod.POST)
public Boolean getAllArchivedpplications(#RequestBody String schemeJson) {
List<SchemeApplication> accList = null;
try {
accList = new ArrayList<SchemeApplication>();
if (StringUtils.isNotEmpty(schemeJson)) {
JSONObject listObject = new JSONObject(schemeJson);
JSONArray entryArray = listObject.getJSONArray("array");
for (int i = 0; i < entryArray.length(); i++) {
JSONObject res = new JSONObject(entryArray.get(i).toString());
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
schemeApplication doc = mapper.readValue(res.toString(),
new TypeReference<schemeApplication>() {
});
accList.add(doc);
}
schemeService.getDao().save(accList); // Service.save accountlist;
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
#RequestBody must work on an object.
Standard way to do this kind of work in two ways:
Form a class having class files with same name and structure with your json data you are sending and capture that data in by #RequestBody annotation
As you are sending data as String, send it as request param, and use #RequestParam instead of #RequestBody and parse the way you need to do things. For I think for this kind of arrayList of bulk data you are working with, option 1 will be better/feasible.
For details you can check here: #RequestBody and #ResponseBody annotations in Spring
I've a response class
public class ResponseModel<T> {
private boolean isRequestSuccessful;
public boolean getIsRequestSuccessful() {
return this.isRequestSuccessful;
}
public void setIsRequestSuccessful(boolean isRequestSuccessful) {
this.isRequestSuccessful = isRequestSuccessful;
}
private String message;
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
private T object;
public T getObject() {
return this.object;
}
public void setObject(T object) {
this.object = object;
}
}
My API will return type T. I would like to parse the response from the API and create a object of type ResponseModel.
I am trying to achieve something like below which I can do it easily with c#. Please help on how to do this with Java
public static ResponseModel<T> Get(String requestUri) throws ClientProtocolException,IOException {
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet(requestUri);
httpGet.addHeader("TenantKey", TenantKey);
httpGet.addHeader("accept", "application/json");
HttpResponse response = client.execute(httpGet);
ResponseModel<T> responseModel = new ResponseModel<T>();
if (response.getStatusLine().getStatusCode() == 200) {
Gson gson = new GsonBuilder().create();
// parse the response as T and and assign to object of ResponseModel
responseModel.object = ...
}
else
{
responseModel.message = response.getEntity().getContent();
}
// return ResponseModel here
}
Generics in C# and Java are pretty different. Simply spoken, there is no sense in what you are doing here.
The java generic T you are using there is a compile time feature. It allows you to use more specific types at compile time, instead of using Object all over the place.
Therefore you can't use generics to determine a "T" at "runtime", as you probably intend to. That T in your method comes from the "outside", and the compiler determines that in occasion it should be a ResponseModel<Integer> and ResponseModel<Whatever> in another context.
You can't have gson read JSON data to return a specific ResponseModel<Whatever> for you. If at all, you might be able to use TypeAdapter magic that does some switching based on the actual value, to return this or that specific ResponseModel<Foo>.
Beyond that: when using such bean like classes as your ResponseModel, you simply want them to be specific, not generic.
Not sure, but I had a similar requirement, but its for Android though. Here is the reference link, where I had to write a generic class to load the different forms of JSON from Assets folder and parse to POJO class.
https://github.com/gokulnathperiasamy/Android-Helper/blob/master/JSONHelper.java
Code:
private static String convertJSONtoEntity(String jsonString, String typeString) {
String jsonObjectString = null;
try {
JSONObject jsonObject = new JSONObject(jsonString);
jsonObjectString = jsonObject.get(typeString).toString();
} catch (Exception e) {
Log.e(TAG, e.getLocalizedMessage());
}
return jsonObjectString;
}
private static <T> List<T> fromJsonList(String json, Class<T> clazz) {
Object[] array = (Object[]) java.lang.reflect.Array.newInstance(clazz, 0);
array = new Gson().fromJson(json, array.getClass());
List<T> list = new ArrayList<>();
if (array != null && array.length > 0) {
for (Object anArray : array) {
list.add(clazz.cast(anArray));
}
}
return list;
}
Usage:
Invoke convertJSONtoEntity() with your jsonString and typeString will be your root element of your JSON.
Invoke the fromJsonList() with value returned by convertJSONtoEntity() and Class. This gives list of objects from JSON.
With the help of other answers and further searching in Google, I ended up with the following code
public static <T> ResponseModel<T> Get(Class<?> classType, String requestUri) throws ClientProtocolException, IOException
{
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet(requestUri);
httpGet.addHeader("accept", "application/json");
HttpResponse response = client.execute(httpGet);
ResponseModel<T> responseModel = new ResponseModel<T>();
if (response.getStatusLine().getStatusCode() == 200)
{
responseModel.setObject((T) Utils.fromJson(EntityUtils.toString(response.getEntity()), classType));
responseModel.setIsRequestSuccessful(true);
}
else
{
responseModel.setMessage(response.getEntity().getContent().toString());
responseModel.setIsRequestSuccessful(false);
}
return responseModel;
}
I am working on a JavaFX project in which I am making network calls with Task. Unfortunately, I have not been able to find how I can pass arguments to it. I have searched many links, but none of them provides. One link from java2s claims they are passing, but the code does not reflect that.
As you can see from the code below, I am using a for-loop and passing the ID parameter of RestGroupAccount in the URL. This time it's okay because I anyways need all of the RestCanvas.
But I am interested in knowing how to give parameters to Task
Code :
private Task<List<RestCanvas>> fetchCanvases = new Task<List<RestCanvas>>() {
#Override
protected List<RestCanvas> call() throws Exception {
List<RestCanvas> list = new ArrayList<>();
try{
for(RestGroupAccount groupAccount : groupAccounts) {
RestTemplate rest = StaticRestTemplate.getRest();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", "JSESSIONID=" + StaticRestTemplate.jsessionid);
HttpEntity<RestCanvas> requestEntity = new HttpEntity<>(requestHeaders);
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<RestCanvas[]> responseEntity = rest.exchange(getCanvasForGroupAccount+groupAccount.getGroupId(), HttpMethod.GET, requestEntity, RestCanvas[].class);
RestCanvas[] restCanvasArray = responseEntity.getBody();
Collections.addAll(list, restCanvasArray);
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
};
If any more information is required, kindly let me know. Thank you.
I had a similar need, where I needed to create tasks that would take in a File and perform tasks on it. In my case I needed to do different things with files in multiple places, so I created the following class:
public abstract class FileOperationTask<V> extends Task<V> {
protected File file;
public FileOperationTask(File file) {
this.file = file;
}
}
This allows me in my controllers to define the following:
FileOperationTask<List<RaffleTicket>> task = new FileOperationTask<List<RaffleTicket>>(file){
#Override
protected List<RaffleTicket> call() throws Exception {
this.file.toString();
return null;
}
};
new Thread(task).run();
As you can see, I'm able to operate on the File object, and implementing my asynchronous task is now more or less identical to implementing a normal task.
If you need to use the code inside your Task more than once, you should consider creating non-anonymous subclass and instantiate it every time you need it with the construction parameter.
In your example this might be:
private Task<List<RestCanvas>> fetchCanvases = new MyTask(getCanvasForGroupAccount + groupAccount.getGroupId());
// ...
// please don't use this name :)
private static class MyTask extends Task<List<RestCanvas>> {
private final String id;
public MyTask(String id) {
this.id = id;
}
#Override
protected List<RestCanvas> call() throws Exception {
List<RestCanvas> list = new ArrayList<>();
try{
for(RestGroupAccount groupAccount : groupAccounts) {
RestTemplate rest = StaticRestTemplate.getRest();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", "JSESSIONID=" + StaticRestTemplate.jsessionid);
HttpEntity<RestCanvas> requestEntity = new HttpEntity<>(requestHeaders);
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<RestCanvas[]> responseEntity = rest.exchange(id, HttpMethod.GET, requestEntity, RestCanvas[].class);
RestCanvas[] restCanvasArray = responseEntity.getBody();
Collections.addAll(list, restCanvasArray);
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
}
I am new to Android development. Here, I am making a GET call like this -
protected String doInBackground(String... params) {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("email", "guest#example.com"));
JSONHttpClient jsonHttpClient = new JSONHttpClient();
ProductDetail[] products = jsonHttpClient.Get(ServiceUrl.PRODUCT, nameValuePairs, ProductDetail[].class);
return null;
}
This is the GET call in JSONHttpClient file -
public <T> T Get(String url, List<NameValuePair> params, final Class<T> objectClass) {
DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Accept", "application/json");
httpGet.setHeader("Accept-Encoding", "gzip");
httpGet.setHeader("Authorization", "Bearer <code>");
HttpResponse httpResponse = defaultHttpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
if (httpEntity != null) {
InputStream inputStream = httpEntity.getContent();
Header contentEncoding = httpResponse.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
inputStream = new GZIPInputStream(inputStream);
}
String resultString = convertStreamToString(inputStream);
inputStream.close();
return new GsonBuilder().create().fromJson(resultString, objectClass);
}
return null;
}
And this is my ProductDetail class -
public class ProductDetail {
public int Id;
public String Name;
}
On running this, I am getting below error -
No-args constructor for class com.compa.ProductDetail does not exist. Register an InstanceCreator with Gson for this type to fix this problem.
This is thrown on this line in JSONHttpClient file -
return new GsonBuilder().create().fromJson(resultString, objectClass);
Can anyone help on this?
In my web api, I am creating json like this (proddetails is a C# IEnumerable object) -
json = JsonConvert.SerializeObject(proddetails);
var response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(json, Encoding.UTF8, "application/json");
return response;
The structure of response json is -
[
{
"Id": 1,
"Name": "First"
},
{
"Id": 2,
"Name": "Second"
}
]
The Gson user guide (https://sites.google.com/site/gson/gson-user-guide) tells you that a well behaved class (meant for serialization and deserialization) should have a no argument constructor. If this is not there, it advises you to use InstanceCreator.
Even if you do not have a constructor, Gson will create an ObjectConstructor for your class. But this is not safe always and has it's own limitations. This question on SO goes more into the details: Is default no-args constructor mandatory for Gson?
NOTE: Please see that if this is an inner class, then it MUST have a constructor as explained in the documentation.
EDIT: Your json is an array. So you need to have the specified number of array objects in the containing class. So you can do the following and then cast:
public class ProductDetailArray {
public ProductDetailArray[] array;
public static ProductDetail {
public ProductDetail() {} // You can also make the constructor private if you don't want anyone to instantiate this
public int Id;
public String Name;
}
}
Once you cast your json similarly as before:
ProductDetailArray obj = GsonBuilder.create().fromJson(response, ProductDetailArray.class);
ProductDetail one = obj.array[0];
ProductDetail two = obj.array[1];
And then you can do your manipulation.. also you should probably be using Gson.fromJson() rather than the GsonBuilder
I am trying to parse JSON from a URL to then add data to an array.
I am using the GSON library.
My JSON has the following format:
[
{
"img-src":"http://website.com/images/img1.png",
"URL":"http://google.com"
},
{
"img-src":"http://website.com/images/img2.jpg",
"URL":"http://yahoo.com"
}
]
I want to grab the above data in a separate thread, I have the following code:
public class Async extends AsyncTask<String, Integer, Object>{
#Override
protected String doInBackground(String... params) {
return null;
}
}
How do I go about grabbing each "img-src" and "URL" values?
Use this method to fetch your Data in an Array list
public ArrayList<NewsItem> getNews(String url) {
ArrayList<NewsItem> data = new ArrayList<NewsItem>();
java.lang.reflect.Type arrayListType = new TypeToken<ArrayList<NewsItem>>(){}.getType();
gson = new Gson();
httpClient = WebServiceUtils.getHttpClient();
try {
HttpResponse response = httpClient.execute(new HttpGet(url));
HttpEntity entity = response.getEntity();
Reader reader = new InputStreamReader(entity.getContent());
data = gson.fromJson(reader, arrayListType);
} catch (Exception e) {
Log.i("json array","While getting server response server generate error. ");
}
return data;
}
This should be how you should declare your ArrayList Type class (here its NewsItem)
import com.google.gson.annotations.SerializedName;
public class NewsItem {
#SerializedName("title")
public String title;
#SerializedName("content")
public String title_details;
#SerializedName("date")
public String date;
#SerializedName("featured")
public String imgRawUrl;
}
Here is the WebSErvice Util Class.
public class WebServiceUtils {
public static HttpClient getHttpClient(){
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
int timeoutConnection = 50000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 50000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpClient httpclient = new DefaultHttpClient(httpParameters);
return httpclient;
}
}
That's the code I use (working well for me).
//Initialize the list
Type listType = new TypeToken<ArrayList<YourObject>>(){}.getType();
//Parse
List<YourObject> List= new Gson().fromJson(response, listType);
YourObject should be something like :
public class Category {
private String URL;
private String img-src;
public Category(String URL, String img-src){
this.URL= URL;
this.img-src= img-src;
}
}
Regards.
Ps: With this you will obtain a list of "YourObject". Then you can create to list one with the URL and other with img-src
In this user guide you can find a lot of examples:
https://sites.google.com/site/gson/gson-user-guide