HTTP 500 Internal server error, in android release build - android

I have a retrofit call to my server that returns JSON data. I have been working on the debug build since the first day and everything looked fine. Just yesterday I generated a release build (android) and found the call is failing with exception as "HTTP 500, internal server error".
I am unable to understand what is the difference between the two that I fall into such a state.
Code to make the retrofit is as under,
public void populateFeeds(final String market, final String category, final String msaToken, final String language, final List<CategorizedFeeds> categorizedFeedsList){
VmFeedsHub.this.feedClusterDataSetUpdate.set(false);
VmFeedsHub.this.feedCategoryDataSetUpdate.set(false);
BackendFactory.getFeedsServiceBackend().getFeedsMetadata(market, category, null, null)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Feeds>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
ALog.i(TAG, LOG_PREFIX + " Feeds data retrieved empty/null for market: " + market + " with exception: " + e.getMessage());
}
#Override
public void onNext(Feeds feeds) {
ALog.i(TAG, LOG_PREFIX + " Feeds data retrieved successfully with feed count: " + feeds.getFeedsMetaDataArrayList().size() + " for market: " + market);
for (CategorizedFeeds categorizedFeeds : feeds.getFeedsMetaDataArrayList()) {
List<FeedMetadata> feedMetadataList = new ArrayList<>();
for(FeedsMetadata feedsMetadata : categorizedFeeds.getFeedsMetadataArrayList()){
FeedMetadata feedMetadata = new FeedMetadata(feedsMetadata.getHeadlineText(), feedsMetadata.getHeadlineImageURL(), feedsMetadata.getProviderName(), feedsMetadata.getProviderImageURL(), feedsMetadata.getPublishedDateTime(), feedsMetadata.getFeedURL(), feedsMetadata.getCmsId());
feedMetadataList.add(feedMetadata);
}
CategorizedFeeds categorizedFeed = new CategorizedFeeds(categorizedFeeds.getCategory(), feedMetadataList);
categorizedFeedsList.add(categorizedFeed);
}
if(category.equals(CATEGORY_CLUSTER))
VmFeedsHub.this.feedClusterDataSetUpdate.set(true);
else
VmFeedsHub.this.feedCategoryDataSetUpdate.set(true);
}
});
}

My solution for this issue is to keep the model classes for retrofit.
Add this code in your proguard-rules.pro file
# keep model classes for retrofit
# packagename.directory.** { *; }
-keep class com.packagename.mac.model.** { *; }
-keep class com.packagename.mac.data.response.** { *; }

I figured out the problem here was with the POST body that I was sending. In the custom Object the proguard was renaming the variables and hence server was unable to intercept them. Added #SerializedName annotation fixed the issue.

-keep class com.packagename.path_name_to_models
give the path to the model classes you are using, the issue will be solved

Related

retrofit calling id from url

How I use these query in retrofit network call and display it in category wise result
https://api.themoviedb.org/3/genre/{genre_id}/movies
Perhaps this could help:
interface class
public interface TheApiInterface{
#GET("url/bits/until/{path_variable}/then/more/url")
Call<TheThingResponse> getTheThing(#Path("path_variable") String var);
}
Activity or whatever:
public class ThePlaceYoureCallingItFrom {
//set up the api interface and http client
public TheApiInterface getApi(){
String endpoint = "https://api.root.site/api/";
//set up retrofit object
return new Retrofit.Builder().baseUrl(endpoint)
//add chosen converter factory for pojo serialization
.addConverterFactory(GsonConverterFactory.create())
//add the OKHTTP client
.client(new OkHttpClient.Builder().build())
//now gimme
.build().create(TheApiInterface.class);
}
public void callGetTheThing(){
//create call
Call<TheThingResponse> call = getApi().getTheThing("somePathVar");
//set callback
ThingResponseCallback callback = new ThingResponseCallback(this, THING_RESPONSE_INTENT_FILTER);
//fire
call.enqueue(callback);
}
}
the callback:
public class ThingResponseCallback implements Callback<TheThingResponse>{
#Override
public void onResponse(Call<TheThingResponse> call, Response<TheThingResponse> response) {
if (response.isSuccessful() && response.body() != null) {
Log.i(TAG, "onResponse: success: theResponseFieldIWant1: " + response.theResponseFieldIWant1;);
} else {
Log.i(TAG, "onResponse: something went wrong with the response object " +response.body());
}
}
#Override
public void onFailure(Call<TheThingResponse> call, Throwable t) {
Log.i(TAG, "onFailure: to: " + call.request().url() + " req " + call.request());
}
}
the response pojo:
public class TheThingResponse{
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse1")
public String theResponseFieldIWant1;
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse2")
public String theResponseFieldIWant2;
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse3")
public String theResponseFieldIWant3;
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse4")
public String theResponseFieldIWant4;
}
the JSON you're receiving would look like this:
{
"theJsonKeyOfTheFieldReturnedInServerResponse1": "the value I wanted 1",
"theJsonKeyOfTheFieldReturnedInServerResponse2": "the value I wanted 2",
"theJsonKeyOfTheFieldReturnedInServerResponse3": "the value I wanted 3",
"theJsonKeyOfTheFieldReturnedInServerResponse4": "the value I wanted 4"
}
but you can build more complex POJOs for more complex JSON.
I've found it useful to make my POJOs all share a Serializable parent class, to make them easy to move about in the Callback, but you could also use a ContentProvider in here quite readily and insert some rows into a DB or something like that if you want to have a more permanent storage.
But bear in mind this is all async- if you want synchronous Retrofit calls, you can use call.execute()
At least in the "retrofit" library, it works like this
#GET("/url/{id}")
suspend fun getNews(
#Path("id") searchById:String
):Response<News>

Using Mockito with Retrofit 2.0

I'm trying to create unit tests for my api calls(made via Retrofit 2.0) using Mockito.
This seemed to be the most popular blog on using Mockito with Retrofit.
http://mdswanson.com/blog/2013/12/16/reliable-android-http-testing-with-retrofit-and-mockito.html
Unfortunately, it uses earlier versions of Retrofit, and depends on the Callbacks and RetrofitError, which are discontinued from 2.0.
How do you do this with Retrofit 2.0?
P.S.: I'm using RxJava along with retrofit, so something that works with RxJava would be great. Thanks!
on official repository of Retrofit there's an example which can be useful:
https://github.com/square/retrofit/tree/master/retrofit-mock
I've also found: https://touk.pl/blog/2014/02/26/mock-retrofit-using-dagger-and-mockito/
Here you would find this fragment:
Unit Tests
During develop of app, you can send requests the server all time(or
most of time) so it is possible to live without mocked server, it
sucks but is possible. Unfortunately you are not able to write good
tests without the mock. Below there are two unit tests. Actually they
do not test anything but in simple way shows how to mock Retrofit
service using Mockito and Dagger.
#RunWith(RobolectricTestRunner.class)
public class EchoServiceTest {
#Inject
protected EchoService loginService;
#Inject
protected Client client;
#Before
public void setUp() throws Exception {
Injector.add(new AndroidModule(),
new RestServicesModule(),
new RestServicesMockModule(),
new TestModule());
Injector.inject(this);
}
#Test
public void shouldReturnOfferInAsyncMode() throws IOException {
//given
int expectedQuantity = 765;
String responseContent = "{" +
" \"message\": \"mock message\"," +
" \"quantity\": \"" + expectedQuantity + "\"" +
"}";
mockResponseWithCodeAndContent(200, responseContent);
//when
EchoResponse echoResponse = loginService.getMessageAndQuantity("test", "test");
//then
assertThat(echoResponse.getQuantity()).isEqualTo(expectedQuantity);
}
#Test
public void shouldReturnOfferInAsyncModea() throws IOException {
//given
int expectedQuantity = 2;
String responseContent = "{" +
" \"message\": \"mock message\"," +
" \"quantity\": \"" + expectedQuantity + "\"" +
"}";
mockResponseWithCodeAndContent(200, responseContent);
//when
EchoResponse echoResponse = loginService.getMessageAndQuantity("test", "test");
//then
assertThat(echoResponse.getQuantity()).isEqualTo(expectedQuantity);
}
protected void mockResponseWithCodeAndContent(int httpCode, String content) throws IOException {
Response response = createResponseWithCodeAndJson(httpCode, content);
when(client.execute(Matchers.anyObject())).thenReturn(response);
}
private Response createResponseWithCodeAndJson(int responseCode, String json) {
return new Response(responseCode, "nothing", Collections.EMPTY_LIST, new TypedByteArray("application/json", json.getBytes()));
}
Read also: Square retrofit server mock for testing
Hope it help

How to get simple JSON object in Retrofit 2.0.0 beta 1?

I am trying to convert this simple response that looks like this
{
"field_one": "bearer",
"field_two": "fgh",
"field_three": 0
}
I am using latest version of Retrofit 2.0.0-beta1. I never used Retrofit before. There are many tutorials and example of old version of Retrofit. I tried different techniques that works with older versions but thats not working with latest one. Due to lack of documentation of latest version of Retrofit I could not find solution.
I want to use latest version.
Here is POJO
public class Auth {
#SerializedName("field_one")
#Expose
private String fieldOne;
#SerializedName("field_two")
#Expose
private String fieldTwo;
#SerializedName("field_three")
#Expose
private Integer fieldThree;
// setter and getter etc. etc.
}
Here is Interface that I am using
interface Authorization {
#Headers("Authorization: This is some header")
#GET("api/v1/mytoken")
Call<Auth> getToken();
}
This is the way I am calling service
OkHttpClient client = new OkHttpClient();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://myendpoint.com/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
Authorization serviceAuthorization = retrofit.create(Authorization.class);
serviceAuthorization.getToken().enqueue(new Callback<Auth>() {
#Override
public void onResponse(Response<Auth> response) {
Log.d("Response", ">>> "+ response.toString());
}
#Override
public void onFailure(Throwable t) {
Log.d("fail", ">>> "+ t.getMessage());
}
});
I am unable to get output. It just print this
Response: >>> retrofit.Response#2567e2c3
I want to get data in Auth Object that I will use later.
Please suggest me best solution
Thanks!
I guess that you are not seeing you are expecting to see your object printed out on this line --
Log.d("Response", ">>> "+ response.toString());
That is going to call the toString method on the response. If you want to call it on your deserialized object, call the body() method first --
if(response.isSuccess()) {
Log.d("Response", ">>> "+ response.body().toString());
} else {
Log.d("Response", "Error - " + response.code())
}

Retrofit-like library with disk cache support

I'm using Retrofit library from network calls. Pretty awesome. But I'm missing caching support. I can't using cache on HTTP layer (via Cache headers). Currently, I'm implementing custom caching with ObjectCache, but it's so complicated. It just should be awesome extend current Retrofit with #Cache(Expire.ONE_DAY) anotation.
My current code is like:
public static void getRestaurant(int restaurantId, String token, boolean forceNetwork, final Callback<Restaurant> listener) {
final String key = "getRestaurant-" + restaurantId + "-" + token;
Restaurant restaurant = (Restaurant) getCacheManager().get(key, Restaurant.class, new TypeToken<Restaurant>() {}.getType());
if (restaurant != null && !forceNetwork) {
Log.d(TAG, "Cache hit: " + key);
// Cache
listener.success(restaurant);
} else {
Log.d(TAG, "Network: " + key);
// Retrofit
getNetwork().getRestaurant(restaurantId, token, new retrofit.Callback<Response>() {
#Override
public void success(Response response, retrofit.client.Response response2) {
getCacheManager().put(key, response.result.restaurant, CacheManager.ExpiryTimes.ONE_HOUR.asSeconds(), true);
listener.success(response.result.restaurant);
}
#Override
public void failure(RetrofitError error) {
listener.failure(error.getLocalizedMessage());
}
});
}
}
Now, it's just a lot of boilerplate code for each method.
Or do you know any library like Retrofit with caching support?
Thanks!
You can wrap the underlying Client and use the request URL as a cache key.
public class CachingClient implements Client {
private final Client delegate;
#Override public Response execute(Request request) {
if (!"GET".equals(request.method())) {
return delegate.execute(request);
}
String url = request.url();
// TODO look up 'url' in your cache.
if (cacheHit) {
return createResponse(cacheResult);
}
// Cache miss! Execute with the real HTTP client.
Response response = delegate.execute(request);
// TODO cache 'response' in your cache with the 'url' key.
return response;
}
}
With Retrofit v2 we are looking to enable this kind of functionality with interceptors which will not only give you a hook into the request/response chain but also allow looking up a custom annotation like #Cache.

Error in obtaining public access token for Mobli

I am having is issues in obtaining the public access token for my app. I am getting the following error:
05-26 14:43:17.194: D/Mobli(1219): Response {"error":"invalid_request","error_description":"The request includes an unsupported parameters","error_uri":"http://dev.mobli.com/error/invalid_request"}
The code that I am using to make the request is as follows:
Mobli mobli = new Mobli(ID, SECRET);
SampleRequestListener mobliListner = new SampleRequestListener();
runner = new AsyncMobliRunner(mobli);
runner.obtainPublicToken(mobliListner, null);
public class SampleRequestListener extends BaseRequestListner {
public void onComplete(final String response, final Object state) {
try {
// process the response here: executed in background thread
Log.d("Mobli", "Response " + response.toString());
} catch (MobliError e) {
Log.w("Mobli Error", "Error" + e.getMessage());
}
}
}
Any idea what might be wrong with the code?
I have also verified that the URL is formed correctly. I am getting the filenotfoundexcetion in util.java
Turns out there was as an issue in openUrl function in util.java that is a part of mobli sdk. In the openUrl function an extra parameter was being appended to the post request, which was resulting in the above error. Specifically, commenting out the following lines in openUrl function solved the above issue.
// use method override
if (!params.containsKey("method")) {
params.putString("method", method);
}

Categories

Resources