Retrofit2 and JacksonConverterFactory error with Adapter - java

I'm developing an application that uses Retrofit2 to upload some photos to a server, this is my code:
public static class NetworkClient {
private static final String BASE_URL = "http://myServer/";
private static Retrofit retrofit;
public static Retrofit getRetrofitClient(Context context) {
if (retrofit == null) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(JacksonConverterFactory.create())
.build();
}
return retrofit;
}
}
public interface UploadAPIs {
#Multipart
#POST("tools/index.php/testUpload/do_upload")
Call<SimpleAdapter> uploadAttachment(#Part MultipartBody.Part filePart);
}
but when I try I get the following error:
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class android.widget.SimpleAdapter]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: java.io.InputStreamReader#a0717cf; line: 1, column: 2]

Related

I want to work with multiple base url in retrofit2

I have a structure whose base url address is constantly variable. When my user changes his location in the application, I change the base url to show the closest server to him. but the retrofit client does not regenerate even though I restart the activities and change all the static variables. The only way to do this is to close the application completely and restart it.
I don't have a fixed base url. There could be 4 different locations today, 12 different locations tomorrow. so i need to find a permanent solution.
I have examined a lot in debug mode, but; When the base url changes, it never goes inside the getClient and cannot reassign the base url.
public static Retrofit retrofit = null;
// I want this address to change.
public static String baseUrl = "";
#Provides
public static Retrofit getClient() {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
#Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return new Date(json.getAsJsonPrimitive().getAsLong());
}
});
Gson gson = builder.create();
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("AUTHORIZATION", "" + JWT_TOKEN)
.build();
return chain.proceed(request);
}
}).build();
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
return retrofit;
}
return retrofit;
}
You can use a dynamic URL in your application during runtime. Retrofit2 introduced the #Url annotation that allows us to pass a complete URL for an endpoint:
#GET
public Call<ResponseBody> profilePicture(#Url String url);
EDITED
You should create a new Retrofit instance when you want to use a new base URL.
public class ServiceGenerator {
public static String apiBaseUrl = "http://futurestud.io/api";
private static Retrofit retrofit;
private static Retrofit.Builder builder =
new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiBaseUrl);
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
// No need to instantiate this class.
private ServiceGenerator() {
}
public static void changeApiBaseUrl(String newApiBaseUrl) {
apiBaseUrl = newApiBaseUrl;
builder = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiBaseUrl);
}
public static <S> S createService(Class<S> serviceClass, AccessToken token) {
String authToken = token.getTokenType().concat(token.getAccessToken());
return createService(serviceClass, authToken);
}
// more methods
// ...
}
https://futurestud.io/tutorials/retrofit-2-how-to-change-api-base-url-at-runtime-2
I used SharedPreferences to handle this problem:
#Singleton
#Provides
suspend fun getBaseUrl(preferencesManager: PreferencesManager): String {
return preferencesManager.getPrefBaseUrl()
}
#Singleton
#Provides
fun provideGsonBuilder(): Gson {
return GsonBuilder()
.setLenient()
.create()
}
#Provides
#Singleton
fun provideOkHttpClient( ) =
OkHttpClient
.Builder()
.connectTimeout(3, TimeUnit.MINUTES)
.readTimeout(3, TimeUnit.MINUTES)
.writeTimeout(3, TimeUnit.MINUTES)
.build()
#Singleton
#Provides
fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient, preferencesManager: PreferencesManager): Retrofit.Builder {
return Retrofit.Builder()
.baseUrl( preferencesManager.getPrefBaseUrl())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okHttpClient)
}
#Singleton
#Provides
fun provideBlogService(retrofit: Retrofit.Builder): MyApi {
return retrofit
.build()
.create(MyApi::class.java)
}

Fetch data from server using retrofit method

i want fetch data from server, i have API URL like example : https://example.com/PlanController/getData/2/7k Plan, int his api url 2 is dynamic value and 7k plan is also dynamic Value. i want fetch data from retrofit method. give me some examples.
public interface APIService {
#GET("PlanController/getData")
Call<CoachListResponse> getAllData();
}
Retrofit clint
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
Gson gson = new GsonBuilder().setLenient().create();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
}
Define service after creating the retrofit
public interface APIService {
#GET("getData/{id}/{kid}")
Call<CoachListResponse> getAllData(#Path("id") Long id, #Path("kid") String kid);
}
public class RetrofitClient {
private static APIService service;
public static Retrofit getClient(String baseUrl) {
Gson gson = new GsonBuilder().setLenient().create();
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson)).build();
}
service = retrofit.create(APIService.class);
return retrofit;
}
public static void getAllData(Callback<CoachListResponse> callback) {
Call<CoachListResponse> regionsCall = service.getAllData();
regionsCall.enqueue(callback);
}
}
, consume
RetrofitClient.getClient("https://example.com/PlanController/").getAllData(new Callback<CoachListResponse>() {
#Override
public void onResponse(Call<CoachListResponse> call, Response<CoachListResponse> response) {
CoachListResponse responseDto = response.body();
// logic
}
#Override
public void onFailure(Call<CoachListResponse> call, Throwable t) {
// logic
}
}, );
I wanted to replace only a part of the URL, and with this solution, I don't have to pass the whole URL, just the dynamic part and Your Retrofit client as it is no need to change:
public interface APIService {
#GET("PlanController/getData/{value}/{plan}")
Call<CoachListResponse> getAllData(#Path(value = "value", encoded = true) String value, #Path(value = "plan", encoded = true) String plan);
}

is not public in 'retrofit2.Retrofit' , cannot be accessed from outside

im new in retrofit and im using retrofit2 version 2.4.0 . there is my Api client code :
public class ApiClient {
public static final String BASE_URL = "https://api.coinmarketcap.com/v1/";
public static Retrofit retrofit = null;
public static Retrofit getApiClient (){
if (retrofit == null){
retrofit = new Retrofit().Builder.baseUrl(BASE_URL).
addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
}
this is my error : is not public in 'retrofit2.Retrofit' , cannot be accessed from outside
its showing me error on this part of the code : new Retrofit().Builder
You need to instantiate Retrofit like this
public class ApiClient {
public static final String BASE_URL = "https://api.coinmarketcap.com/v1/";
public static Retrofit retrofit = null;
public static Retrofit getApiClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
I had the same problem.
Use Retrofit.Builder() instead of Retrofit().Builder().

retrofit2: adding RequestInterceptor

Guys please am trying to upgrade from retrofit 1 to retrofit 2 but am having a hard time adding a request interceptor for all requests.
In retrofit 1, I achieved it by doing something like this;
public static <S> S createService(Class<S> serviceClass, final String token) {
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(Constant.APP_URL);
builder.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addHeader("token", token);
}
});
RestAdapter adapter = builder.build();
return adapter.create(serviceClass);
}
But i just cant get my head around this in retrofit 2... Please does anyone have a solution to my problem?
In your dependencies block add:
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
In your Retrofit service class add:
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
then add:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL)
.client(client) // this is the line you care about
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(JacksonConverterFactory.create())
.build();

Unable to create converter for java.util.List Retrofit 2.0.0-beta2

I'm just doing a GET request, but I'm getting this error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.yomac_000.chargingpoint/com.example.yomac_000.chargingpoint.AllStores}: java.lang.IllegalArgumentException: Unable to create converter for java.util.List
And it's because of this line of code:
Call<List<Store>> call = subpriseAPI.listStores(response);
So I had tried with this line of code to see what type it is:
System.out.println(subpriseAPI.listStores(response).getClass().toString());
But then I get the same error so it doesn't let me know what type it is. Here below you can see my code.
StoreService.java:
public class StoreService {
public static final String BASE_URL = "http://getairport.com/subprise/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.build();
SubpriseAPI subpriseAPI = retrofit.create(SubpriseAPI.class);
String response = "";
public List<Store> getSubprises() {
Call<List<Store>> call = subpriseAPI.listStores(response);
try {
List<Store> listStores = call.execute().body();
System.out.println("liststore "+ listStores.iterator().next());
return listStores;
} catch (IOException e) {
// handle errors
}
return null;
}
}
SubpriseAPI.java:
public interface SubpriseAPI {
#GET("api/locations/get")
Call<List<Store>> listStores(#Path("store") String store);
}
Store.java:
public class Store {
String name;
}
I'm using Retrofit version 2.0.0-beta2.
In the 2+ version you need to inform the Converter
CONVERTERS
By default, Retrofit can only deserialize HTTP bodies into OkHttp's
ResponseBody type and it can only accept its RequestBody type for
#Body.
Converters can be added to support other types. Six sibling modules
adapt popular serialization libraries for your convenience.
Gson: com.squareup.retrofit:converter-gson Jackson: com.squareup.retrofit:converter-jackson
Moshi: com.squareup.retrofit:converter-moshi
Protobuf: com.squareup.retrofit:converter-protobuf
Wire: com.squareup.retrofit:converter-wire
Simple XML: com.squareup.retrofit:converter-simplexml
// Square libs, consume Rest API
compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta1'
So,
String baseUrl = "" ;
Retrofit client = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
public interface SubpriseAPI {
#GET("api/locations/get")
Call<List<Store>> listStores(#Path("store") String store);
}
you declared a #Path called store, so in your #GET annotation retrofit is expecting to find the placeholder for the substitution. E.g.
#GET("api/locations/{store}")
Call<List<Store>> listStores(#Path("store") String store);

Categories