Retrofit Observables and access to Response - retrofit

I'm using Retrofit and RxJava but can't seem to do what I want.
Here's my declaration of my web service:
Observable<Response> rawRemoteDownload(#Header("Cookie") String token, #Path("programId") int programId);
The problem I have is the webservice is returning a 403 and a json payload with details.
Retrofit calls onError, only passing the Throwable so I can't check the response body.
Here's part of my test code
apiManager.rawRemoteDownloadRequest("token", 1).subscribe(new Observer<Response>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
// this is called and I've lost the response!
}
#Override
public void onNext(Response response) {
}
});
SOLUTION:
Thanks to Gomino, I went with this as a solution:
new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
if (throwable instanceof RetrofitError) {
Response response = ((RetrofitError) throwable).getResponse();
System.out.println(convertToString(response.getBody()));
}
}
where convertToString looks like:
private String convertToString(TypedInput body) {
byte[] bodyBytes = ((TypedByteArray) body).getBytes();
return new String(bodyBytes);
}

Check if the throwable is a RetrofitError:
#Override
public void onError(Throwable e) {
if (e instanceof RetrofitError) {
Response response = ((RetrofitError) e).getResponse();
}
}

Related

How to fix apps containing an unsafe implementation of TrustManager and HostnameVerifier

After upload my apps in Google play Store, getting a mail from google that the app are using an unsafe implementation of the TrustManager and HostnameVerifier. How to fix this problem? Can someone give me a direction?
public class HttpsTrustManager implements X509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
#Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
#Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new HttpsTrustManager()};
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());
}
}
I have tried the above code.

Grpc bidirectional Streaming - Can server initiates the message exchange?

My scenario is,
Server and client initiated
server sends message to client ,(server initiating the message exchange)
client receives the message and reply back with the response
If so, Please help me with grpc-java sample code.
All I could find is client sending the message to the server, for that server sends back the response.
Server sending message first can be achieved by Bidirectional-streaming
https://grpc.io/docs/reference/java/generated-code.html
// Client Side:
volatile StreamObserver<Message> requestOb;
StreamObserver<Message> responseOb = new StreamObserver<>() {
#Override public void onNext(Message msg) { requestOb.onNext(msg); }
#Override public void onError(Throwable t) { requestOb.onError(t); }
#Override public void onCompleted() { requestOb.onCompleted(); }
}
requestOb = stub.echoTheServer(responseOb);
// Server side:
#Override
public StreamObserver<Message> echoTheServer(StreamObserver<Message> responseOb) {
for (int i = 0; i < 100; i++) {
responseOb.onNext(new Message());
}
responseOb.onComplete();
return new StreamObserver<Message>() {
#Override public void onNext(Message msg) {}
#Override public void onError(Throwable t) { responseOb.onError(t); }
#Override public void onCompleted() {}
}
}

Multiple Query Params with Asyncronous Call Retrofit

UPDATE:
I have learned what I am looking to do is to use the Async within Retrofit with multiple queries too. I have updated my code, but I cannot get the async with the queries.
I am using Retrofit to make my data calls to a movie database and need to change the sort order depending on user settings. I am not clear how I could add this functionality to my interface.
sort_by=highest_rating.desc
or
sort_by=popularity.desc
Interface:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<MovieDbModel> response);
}
UPDATED API INTERFACE:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie?sort_by=popularity.desc&api_key=xxxxxxx")
void getMoviesByPopularityDesc(Callback<MovieDbModel> response);
#GET("/3/discover/movie?sort_by=vote_average_desc&api_key=xxxxxxxx")
void getMoviesByVotingDesc(Callback<MovieDbModel> response);
}
UPDATED DATA CALL THAT WORKS:
private void makeDataCall(String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
if (sortPreference.equals(this.getString(R.string.sort_order_popularity)) ){
apiLocation.getMoviesByPopularityDesc (new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
} else {
apiLocation.getMoviesByVotingDesc( new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
My call for the data:
private void makeDataCall (String apiKey, String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
apiLocation.getData(apiKey, sortPreference, new Callback<MovieDbModel>){
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
I found a way to do Synchronously, but not asynchronously.
From your question and comment, IHMO, you should import retrofit.Callback; instead of import com.squareup.okhttp.Callback;
My code as the following has no compile error:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// creating a RestAdapter using the custom client
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL_BASE)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient(mOkHttpClient))
.build();
WebService webService = restAdapter.create(WebService.class);
retrofit.Callback<GetRoleData> callback = new Callback<GetRoleData>() {
#Override
public void success(GetRoleData getRoleData, retrofit.client.Response response) {
}
#Override
public void failure(RetrofitError error) {
}
};
webService.getData("api_key", "sort_by", callback);
}
Interface:
public interface WebService {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<GetRoleData> response);
}
So, please check your code again

Spring MVC Jsonp filter incorrect response. (Content length cuts of response output)

I'm trying to implement this Jsonp Filter.
However, whenever I call my url /server/api.jsonp?callback=something it cuts of the last part of the response (ContentLength has the length of the original response output. In this case that would be 15 since {test: 'blaat'} is my original response output - see Controller).atleast this is what I assume since the output I get is test({test: 'bl. Does someone know how to get the filter to work and send the correct response back?
(I even try to force the Content-length - see JsonpCallbackFilter)
Filter:
public class JsonpCallbackFilter implements Filter {
protected final Log logger = LogFactory.getLog(JsonpCallbackFilter.class);
#Override
public void init(FilterConfig fConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
Map<String, String[]> params = httpRequest.getParameterMap();
if (params.containsKey("callback")) {
if (logger.isDebugEnabled()) {
logger.debug("Wrapping response with JSONP callback: " + params.get("callback")[0]);
}
OutputStream out = httpResponse.getOutputStream();
GenericResponseWrapper wrapper = new GenericResponseWrapper(httpResponse);
chain.doFilter(request, wrapper);
byte[] callBack = (params.get("callback")[0] + "(").getBytes();
byte[] callBackEnd = (");").getBytes();
byte[] jsonpResponse = new byte[callBack.length + wrapper.getData().length + callBackEnd.length];
System.arraycopy(callBack, 0, jsonpResponse, 0, callBack.length);
System.arraycopy(wrapper.getData(), 0, jsonpResponse, callBack.length, wrapper.getData().length);
System.arraycopy(callBackEnd, 0, jsonpResponse, callBack.length + wrapper.getData().length, callBackEnd.length);
logger.debug(new String(jsonpResponse));
logger.debug("Length: " + jsonpResponse.length);
out.write(jsonpResponse);
wrapper.setContentType("text/javascript;charset=UTF-8");
wrapper.setContentLength(jsonpResponse.length);
} else {
if (logger.isDebugEnabled()) {
logger.debug("No callback found, resort to default json request!");
}
chain.doFilter(request, response);
}
}
#Override
public void destroy() {
}
}
Generic Response Wrapper:
public class GenericResponseWrapper extends HttpServletResponseWrapper {
private ByteArrayOutputStream output;
private FilterServletOutputStream filterStream;
private PrintWriter printWriter;
private int contentLength;
private String contentType;
public GenericResponseWrapper(HttpServletResponse response) {
super(response);
output = new ByteArrayOutputStream();
filterStream = new FilterServletOutputStream(output);
printWriter = new PrintWriter(output, true);
}
public byte[] getData() {
printWriter.close();
return output.toByteArray();
}
#Override
public ServletOutputStream getOutputStream() {
return filterStream;
}
#Override
public PrintWriter getWriter() {
return printWriter;
}
public int getContentLength() {
return contentLength;
}
#Override
public void setContentLength(int length) {
this.contentLength = length;
super.setContentLength(length);
}
#Override
public String getContentType() {
return contentType;
}
#Override
public void setContentType(String contentType) {
this.contentType = contentType;
super.setContentType(contentType);
}
}
Custom Filter outputstream:
public class FilterServletOutputStream extends ServletOutputStream {
private DataOutputStream stream;
public FilterServletOutputStream(OutputStream output) {
stream = new DataOutputStream(output);
}
#Override
public void write(int b) throws IOException {
stream.write(b);
}
#Override
public void write(byte[] b) throws IOException {
stream.write(b);
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
stream.write(b, off, len);
}
}
web.xml filter mapping:
<filter>
<filter-name>jsonpCallbackFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>jsonpCallbackFilter</filter-name>
<url-pattern>*.jsonp</url-pattern>
</filter-mapping>
bean mapping in applicationContext.xml
<bean id="jsonpCallbackFilter" class="com.world2.utils.spring.filters.jsonp.JsonpCallbackFilter" />
Controller:
#Controller
public class ApiRequests {
protected final Logger logger = Logger.getLogger(ApiRequests.class);
#RequestMapping(value = "api.json", produces = {"application/json"}, method = RequestMethod.GET)
#ResponseBody
public String handleActionJson(final HttpServletRequest request){
return "{test: 'blaat'}";
}
#RequestMapping(value = "api.jsonp", produces = {"text/javascript", "application/javascript", "application/json"}, method = RequestMethod.GET)
#ResponseBody
public String handleActionJsonp(final HttpServletRequest request){
return "{test: 'blaat'}";
}
}
Url I try to call:
http://host:8084/MyProject/server/api.jsonp?callback=test&_=1364980436087
Debug output:
11:13:57,776 DEBUG JsonpCallbackFilter:57 - test({test: 'blaat'});
11:13:57,776 DEBUG JsonpCallbackFilter:58 - Length: 22
Result:
test({test: 'bl
instead of expected result:
test({test: 'blaat'});
Apparently I had to first set the content length and then write the ouput.
Right:
wrapper.setContentType("text/javascript;charset=UTF-8");
wrapper.setContentLength(jsonpResponse.length);
out.write(jsonpResponse);
Wrong:
out.write(jsonpResponse);
wrapper.setContentType("text/javascript;charset=UTF-8");
wrapper.setContentLength(jsonpResponse.length);

Doing Back Ground AsyncTask

I Am Trying to load a dynamic URL for Mediaplayer. How to handle various kinds of exceptions like file not found & timeout Exceptions that arise during execution.
public class MediaAsynchTask extends AsyncTask<String, Void, Object> {
protected void onPreExecute() {
super.onPreExecute();
progress = new ProgressDialog(AudioView.this);
progress.setMessage("LOADING........");
progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progress.setCancelable(true);
progress.show();
}
protected void onPostExecute(Object result) {
super.onPostExecute(result);
if(result!=null){
progress.dismiss();
}else{
Audio.this.finish();
}
}
Protected Object doInBackground(String... params) {
try {
if (!true)
{
MediaPlayer m = MediaPlayer.create(Audio.this,Uri.parse("audiourl.mp3"));
myProgressBar.setMax(mMediaPlayer.getDuration());
}return mMediaPlayer;
}catch (Exception e) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(),"Check Your NetWork and Data Connection",Toast.LENGTH_LONG).show();
}
});
}
return mMediaPlayer;
}
}
its very simple you can do it like this:
try{
**//your code goes here**
}catch(FileNotFoundException exception){
//handle exception
}//**handle other possible exceptions**
catch(JsonParseException exception){
exception.printStackTrace();
}catch(JsonProcessingException exception){
exception.printStackTrace();
}

Resources