Trying to use bing translator API with Robospice in Android - java

I need to implement robospice for doing the networking part in my Translator app. I previously used async task class and it was working fine, but now i want to improve my application with implementing robospice. I'am trying to execute the following code but it doesn't't throw any exception it just never executes....
#Override
public TranslatedText loadDataFromNetwork() throws Exception {
String jsonString = getJsonString();
String headerValue = getHeaderValue(jsonString);
String text = pair.getWordPairs().getWordFrom();
String languageFrom = pair.getLanguagePairs().getLanguageFrom().getCode();
String languageTo = pair.getLanguagePairs().getLangougateTo().getCode();
String uri = String
.format("http://api.microsofttranslator.com/v2/Http.svc/Translate?text=%s&from=%s&to=%s&contentType=text/html",
URLEncoder.encode(text, "UTF-8"),
URLEncoder.encode(languageFrom, "UTF-8"),
URLEncoder.encode(languageTo, "UTF-8"));
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", headerValue);
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
// Add the Simple XML message converter
getRestTemplate().getMessageConverters().add(new SimpleXmlHttpMessageConverter());
//set the headerValue in the Entity
org.springframework.http.HttpEntity<?> request = new org.springframework.http.HttpEntity<Object>(headerValue);
// Make the HTTP GET request, marshaling the response from XML to an
// EventList
Log.v("request","Making request!");
//This line never finish execuitng, doesen't throw exception or anything in logCat
ResponseEntity<Object> responseEntity = getRestTemplate().exchange(uri, HttpMethod.GET, request, null);
Log.v("request", responseEntity.getBody().toString());
Log.d("Load Data From Network", request.getBody().toString());
return null;
}
The last thing it shows in log cat is Request First!! And nothing after that. It never even gets to The Request Listener onRequestFailure.
Can any 1 tell me what i do wrong ?

This is what look weird to me in your code:
ResponseEntity<Object> and null as 4th parameter of the exchange method are not correct. You need to provide a type which represents the response you get from the server.
The object returned by loadDataFromNetwork() is what you will get in the onRequestSuccess() method. Returning null is not a good idea, in my opinion.

I fixed the problem. So if you need to handle stream you will have to provide the following code
ResponseEntity<byte[]> responseEntity = getRestTemplate().exchange(uri, HttpMethod.GET, request, byte[]);

Related

Java RestTemplate hangs on 204 status code response

I'm creating test framework and using RestTemplate class for HTTP request creation.
In general cases I use next code:
Response response = null;
ResponseEntity<String> responseEntity = null;
try{
responseEntity = getRest().exchange(url, httpMethod, httpEntity, String.class);
response = new Response(
responseEntity.getStatusCodeValue(),
responseEntity.getStatusCode().getReasonPhrase(),
responseEntity.getBody(),
responseEntity.getHeaders()
);
} catch (HttpStatusCodeException e){
response = new Response(
e.getRawStatusCode(),
e.getStatusText(),
e.getResponseBodyAsString(),
e.getResponseHeaders()
);
}
It works perfectly for all cases except DELETE HTTP method which receives 204 status code and empty body as a response.
Now, I have to reinitialize RestTemplate to fix it. But I hope that another way should exist.
Could you help me with this?
Please check if you use HttpMethod.Delete for httpMethod and also try when you use delete to put as last parameter of exchange not String.class but Void.class.
I hope it help you.

How to consume a HTTPS GET service with Spring Boot

I am trying to consume the following HTTPS endpoints from Yahoo Weather Service:
Yahoo Weather Service API
I am doing some special query according to the API to get the current weather at some parametrized location.
#Service("weatherConditionService")
public class WeatherConditionServiceImpl implements WeatherConditionService {
private static final String URL = "http://query.yahooapis.com/v1/public/yql";
public WeatherCondition getCurrentWeatherConditionsFor(Location location) {
RestTemplate restTemplate = new RestTemplate();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(URL);
stringBuilder.append("?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22");
// TODO: Validate YQL query injection
stringBuilder.append(location.getName());
stringBuilder.append("%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys");
WeatherQuery weatherQuery = restTemplate.getForObject(stringBuilder.toString(), WeatherQuery.class);
// TODO: Test Json mapping response
Condition condition = weatherQuery.getQuery().getResults().getChannel().getItem().getCondition();
return new WeatherCondition(condition.getDate(), Integer.parseInt(condition.getTemp()), condition.getText());
}
Location is a class that provides the attribute "name" that is a String description of the location, such as "New York" or "Manila".
Condition an other classes just map the returning object.
When executing I get the following HTTP response:
org.springframework.web.client.HttpClientErrorException: 403 Forbidden
So this means I am not authorized to access the resource from what I understand.
The URL works great if I just copy & paste it in a web browser:
Yahoo Weather Query
I think that mapping is not a problem since I am not getting "400" (Bad Request) but "403" (Forbidden)
There must be some error on the way I use the RestTemplate object. I am researching but I can't find an answer.
The docs say you need an api key. But when I make a call like this:
fetch('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22nome%2C%20ak%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys')
.then(resp=> resp.json())
.then((res)=>console.log(res.query.results))
https://repl.it/NeoM
It works fine without one. Perhaps you've been blackisted for hitting the api too often.
Your code seems fine.
I finally found the answer. It finally WAS a Bad Request because I needed to pass the parameters differently (not as part of the URL).
I found the answer here. Here goes the code for my particular Yahoo Weather API call return a String (I still will have to do some work to use the mapping).
private static final String URL = "http://query.yahooapis.com/v1/public/yql";
public String callYahooWeatherApi() {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(URL)
.queryParam("q", "select wind from weather.forecast where woeid=2460286")
.queryParam("format", "json");
HttpEntity<?> entity = new HttpEntity<>(headers);
HttpEntity<String> response = restTemplate.exchange(
builder.build().encode().toUri(),
HttpMethod.GET,
entity,
String.class);
return response.getBody();
}

Log Response content in spring HandlerInterceptorAdapter postHandle

I have implemented the below method to log response , but it throws an exception at IOUtils.toString(responseWrapper.getContentInputStream(), "UTF-8"); saying response has zero bytes . I am able to access headers and status. how can I get the response body?
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("after Request");
ObjectMapper objectMapper = new ObjectMapper();
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
HttpStatus responseStatus = HttpStatus.valueOf(responseWrapper.getStatusCode());
System.out.println(responseWrapper.getStatusCode());
HttpHeaders responseHeaders = new HttpHeaders();
for (String headerName : responseWrapper.getHeaderNames()) {
System.out.println(headerName);
responseHeaders.add(headerName, responseWrapper.getHeader(headerName));
}
String responseBody = IOUtils.toString(responseWrapper.getContentInputStream(), "UTF-8");
System.out.println(responseBody);
log.info("Response body {} ",responseBody);
responseWrapper.copyBodyToResponse();
}
You never use response.getOutputStream() or response.getWriter() so no data is added to the response. That's why it is empty.
Your created entity
ResponseEntity<JsonNode> responseEntity = new ResponseEntity<>(responseJson,responseHeaders,responseStatus);
is never used and never sent to response. Try e.g.
responseWrapper.getWriter().write("test");
and check the body after.
How to read and copy the HTTP servlet response output stream content for logging
has your answer. The reason why getting your response output stream does not work is because the output stream gets written to and flushed regularly as you generate your output. This means that when you attempt to get it at the end, you just have an empty output. Alternatively, if you capture it at the beginning, that just means that your consumption of the outputstream denies the same consumption to your client. This is why you have to copy it as in the answer above.

Strange problems with the Spring RestTemplate in Android application

I began to use RESTful api of the Spring Framework in my android client application. But I have encountered with problems when I tried to execute HTTP request via postForObject/postForEntity methods. Here is my code:
public String _URL = "https://someservice/mobile/login";
public void BeginAuthorization(View view)
{
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> _entity = new HttpEntity<String>(requestHeaders);
RestTemplate templ = new RestTemplate();
templ.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
templ.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
ResponseEntity<String> _response = templ.postForEntity(_URL,_entity,String.class); //HERE APP CRASHES
String _body = _response.getBody();
So the question what am I doing wrong? How to fix this? May there is other way to do it?I really need a help. Thanks in advance!
I think you are targeting your app Android 4.0-4.2. Then you must perform all your operations in the background, not main (UI) thread. You are performing an authorization process, as I see. It's a short operation, so it's better for you to use AsyncTask for this. Here is howto for this on androidDevelopers:
http://developer.android.com/reference/android/os/AsyncTask.html
You should override doInBackground(Params...) in such a way:
class LoginTask extends AsyncTask<String,Void,Void>
{
#Override
protected Void doInBackground(String... params) {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> _entity = new HttpEntity<String>(requestHeaders);
RestTemplate templ = new RestTemplate();
templ.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
templ.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
ResponseEntity<String> _response = templ.postForEntity(params[0],_entity,null) //null here in order there wasn't http converter errors because response type String and [text/html] for JSON are not compatible;
String _body = _response.getBody();
return null;
}
}
And then call it in your BeginAuthorization(View view):
new LoginTask().execute(URL);
P.S. Also if you write Java please use correct naming conventions. Instead of this _response please write response.
From the documentation:
NetworkOnMainThreadException
The exception that is thrown when an application attempts to perform a
networking operation on its main thread.
You should make a thread and do the networking from there. This may be what you are looking for.
from android>= 4.0 network calls must go through asynctack

Calling an RESTFul using Spring-Android

Here is my Strifified json,
{
"Request":{
"Object1":{
"Key1":"Value1"
},
"Object2":{
"Key2":"Value2"
}
},
"Object3":{
"Key3":"Value3"
}
}
I am forming this using Gson. String Stringifiedjson = new Gson().toJson(user);
Here is what i am trying to achive.
RestTemplate rest = new RestTemplate();
String url = "";
String event = rest.getForObject(url, Stringifiedjson);
How would i send to my REST Service and get back my result in onEventHandler or onErrorHandler. I am basically from JavaScript background.
Why does the method getForObject does not accept String, String as params.
Update:
AuthenticateUser user = new AuthenticateUser(credential, Header);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(new MediaType("application","json"));
//HttpEntity<AuthenticateUser> requestEntity = new HttpEntity<AuthenticateUser>(user, requestHeaders);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
String url = "url";
String result = restTemplate.postForObject(url, AuthenticateUser.class, String.class);
Attached is the pastie of what exception i am getting.
http://pastie.org/private/efyfvvbxyxdsvm3lvv7q
About the second question: I just found this example (you could take a look at the entire doc ;) )
2.7.1 Basic Usage Example
The following example shows a query to google for the search term "SpringSource".
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, "SpringSource");
getForObject
public <T> T getForObject(URI url,
Class<T> responseType)
throws RestClientException
Description copied from interface: RestOperations
Retrieve a representation by doing a GET on the URL . The response (if any) is converted and returned.
Specified by:
getForObject in interface RestOperations
Parameters:
url - the URL
responseType - the type of the return value
Returns:
the converted object
Throws:
RestClientException
The exception in your stacktrace could be related to the same issue of this post. The problem occurs when your app tries to make a connection in the main thread.
10-23 15:46:10.106: E/AndroidRuntime(1038): FATAL EXCEPTION: main
10-23 15:46:10.106: E/AndroidRuntime(1038): android.os.NetworkOnMainThreadException
The NetworkOnMainThreadException is thrown when you execute any network operation in your application main ui thread (see also Keeping Your App Responsive. This is not allowed. You'll have to use a background thread for network operation, see Worker threads on http://developer.android.com/guide/components/processes-and-threads.html

Categories